﻿using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Specialized;
using System.Threading.Tasks;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.ScheduleJob.Engine;
using T.FAS.Runtime.ScheduleJob.SPI;

namespace T.FAS.Runtime.ScheduleJob.Service
{
    public class StdSchedulerFacotryRepository
    {
        private NameValueCollection repositoryConfig = null;
        private StdSchedulerFactory factory = null;
        private IScheduler scheduler = null;
        private static readonly object lockobj = new object();
        private static StdSchedulerFacotryRepository _instance = null;
        
        private StdSchedulerFacotryRepository()
        {
            InitRepository().GetAwaiter().GetResult();
        }
        public static StdSchedulerFacotryRepository GetInstance()
        {
            if (_instance == null)
            {
                lock (lockobj)
                {
                    if (_instance == null)
                        _instance = new StdSchedulerFacotryRepository();
                }
            }
            return _instance;
        }
        public async Task InitRepository()
        {
            if(repositoryConfig==null)
                repositoryConfig = new RepositoryConfigService().GetConfig();
            if(factory==null)
                factory = new StdSchedulerFactory(repositoryConfig);
            scheduler = await GetScheduler();
            scheduler.ListenerManager.AddJobListener(new BasicScheduleJobListener());
            await scheduler.Start();
        }
        private async Task<IScheduler> GetScheduler()
        {
            if (factory == null)
                factory = new StdSchedulerFactory(repositoryConfig);
            return await factory.GetScheduler();
        }
        public async Task StartJob(IJobDetail jobDetail, ITrigger trigger)
        {
            await scheduler.ScheduleJob(jobDetail, trigger);
        }
        public async Task UpdateTrigger(TriggerKey triggerKey, ITrigger trigger)
        {
            await scheduler.RescheduleJob(triggerKey, trigger);
        }
        public async Task PauseJob(JobKey jobKey)
        {
            await scheduler.PauseJob(jobKey);
        }
        public async Task ResumeJob(JobKey jobKey)
        {
            await scheduler.ResumeJob(jobKey);
        }
        public async Task DeleteJob(JobKey jobKey)
        {
            await scheduler.DeleteJob(jobKey);
        }
        public async Task GetJobDetail(JobKey jobKey)
        {
            await scheduler.GetJobDetail(jobKey);
        }
        public async Task GetJobTrigger(TriggerKey triggerKey)
        {
            await scheduler.GetTrigger(triggerKey);
        }
        public ScheduleJobExecuteInfo GetScheduleJobExecuteInfo(TriggerKey tKey)
        {
            var trigger = scheduler.GetTrigger(tKey).Result;
            var info = new ScheduleJobExecuteInfo();
            if (trigger != null)
            {
                var preUtc = trigger.GetPreviousFireTimeUtc();
                if (preUtc == null)
                    info.PreFireTime = null;
                else
                    info.PreFireTime = TimeZone.CurrentTimeZone.ToLocalTime(preUtc.Value.DateTime);
                var nextUtc = trigger.GetNextFireTimeUtc();
                if (nextUtc == null)
                    info.NextFireTime = null;
                else
                    info.NextFireTime = TimeZone.CurrentTimeZone.ToLocalTime(nextUtc.Value.DateTime);
            }
            return info;
        }
    }
}
